package com.unitedvision.persistence.domain;

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.unitedvision.core.domain.Company;
import com.unitedvision.core.domain.Debitur;
import com.unitedvision.core.domain.GeneralType;
import com.unitedvision.core.domain.Status;
import com.unitedvision.core.exception.WrongFormatException;

@Entity
@Table (name = "company")
public class CompanyEntity implements Debitur {
	private int id;
	private CustomerEntity customer;
	private String description;
	private Date joinDate;
	private Status status;
	private List<CompanyModuleEntity> companyModules;
	private List<OperatorEntity> operators;
	private List<CompanyCustomerEntity> companyCustomers;
	private List<InventoryEntity> inventories;
	private List<CompanyBillEntity> bills;
	
	public CompanyEntity() {
		super();
	}

	public CompanyEntity(CustomerEntity customer, String description, Date joinDate, Status status) {
		super();
		setCustomer(customer);
		setDescription(description);
		setJoinDate(joinDate);
		setStatus(status);
	}
	
	public CompanyEntity(Company company) throws WrongFormatException {
		super();
		setCustomer(CustomerEntity.create(company.getCustomer()));
		setDescription(company.getDescription());
		setJoinDate(company.getJoinDate());
		setStatus(company.getStatus());
	}

	@Id @GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "customer_id", referencedColumnName = "id")
	public CustomerEntity getCustomer() {
		return customer;
	}

	public void setCustomer(CustomerEntity customerEntity) {
		this.customer = customerEntity;
	}

	@Column (name = "description")
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Temporal (TemporalType.DATE)
	@Column (name = "join_date")
	public Date getJoinDate() {
		return joinDate;
	}

	public void setJoinDate(Date joinDate) {
		this.joinDate = joinDate;
	}

	@Column (name = "status")
	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}
	
	@OneToMany (targetEntity = OperatorEntity.class, mappedBy = "company", fetch = FetchType.LAZY)
	public List<OperatorEntity> getOperators() {
		return operators;
	}

	public void setOperators(List<OperatorEntity> operatorEntities) {
		this.operators = operatorEntities;
	}

	@OneToMany (targetEntity = CompanyCustomerEntity.class, mappedBy = "company", fetch = FetchType.LAZY)
	public List<CompanyCustomerEntity> getCompanyCustomers() {
		return companyCustomers;
	}

	public void setCompanyCustomers(List<CompanyCustomerEntity> companyCustomers) {
		this.companyCustomers = companyCustomers;
	}

	@OneToMany (targetEntity = CompanyModuleEntity.class, mappedBy = "company", fetch = FetchType.LAZY)
	public List<CompanyModuleEntity> getCompanyModules() {
		return companyModules;
	}

	public void setCompanyModules(List<CompanyModuleEntity> companyModules) {
		this.companyModules = companyModules;
	}

	@OneToMany (targetEntity = InventoryEntity.class, mappedBy = "company", fetch = FetchType.LAZY)
	public List<InventoryEntity> getInventories() {
		return inventories;
	}

	public void setInventories(List<InventoryEntity> inventories) {
		this.inventories = inventories;
	}

	@OneToMany (targetEntity = CompanyBillEntity.class, mappedBy = "company", fetch = FetchType.LAZY)
	public List<CompanyBillEntity> getBills() {
		return bills;
	}

	public void setBills(List<CompanyBillEntity> bills) {
		this.bills = bills;
	}

	@Transient
	public String getName() {
		return customer.getName();
	}
	
	@Transient
	public AddressValue getAddress() {
		return customer.getAddress();
	}
	
	@Transient
	public ContactValue getContact() {
		return customer.getContact();
	}
	
	@Transient
	public boolean isActive() {
		return (status == Status.ACTIVE);
	}
	
	@Override
	@Transient
	public GeneralType getPayableCustomer() {
		return getCustomer();
	}

	public Company toCompany() {
		return new Company(id, customer.toCustomer(), description, joinDate, status);
	}
	
	public static CompanyEntity create(CustomerEntity customer, String description, Date joinDate, Status status) {
		return new CompanyEntity(customer, description, joinDate, status);
	}
	
	public static CompanyEntity create(Company company) throws WrongFormatException {
		return new CompanyEntity(company);
	}

	@Override
	public String toString() {
		return "CompanyEntity [id=" + id + ", customer=" + customer
				+ ", description=" + description + ", joinDate=" + joinDate
				+ ", status=" + status + ", companyModules=" + companyModules
				+ ", operators=" + operators + ", companyCustomers="
				+ companyCustomers + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime
				* result
				+ ((companyCustomers == null) ? 0 : companyCustomers.hashCode());
		result = prime * result
				+ ((companyModules == null) ? 0 : companyModules.hashCode());
		result = prime * result
				+ ((customer == null) ? 0 : customer.hashCode());
		result = prime * result
				+ ((description == null) ? 0 : description.hashCode());
		result = prime * result + id;
		result = prime * result
				+ ((joinDate == null) ? 0 : joinDate.hashCode());
		result = prime * result
				+ ((operators == null) ? 0 : operators.hashCode());
		result = prime * result + ((status == null) ? 0 : status.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CompanyEntity other = (CompanyEntity) obj;
		if (companyCustomers == null) {
			if (other.companyCustomers != null)
				return false;
		} else if (!companyCustomers.equals(other.companyCustomers))
			return false;
		if (companyModules == null) {
			if (other.companyModules != null)
				return false;
		} else if (!companyModules.equals(other.companyModules))
			return false;
		if (customer == null) {
			if (other.customer != null)
				return false;
		} else if (!customer.equals(other.customer))
			return false;
		if (description == null) {
			if (other.description != null)
				return false;
		} else if (!description.equals(other.description))
			return false;
		if (id != other.id)
			return false;
		if (joinDate == null) {
			if (other.joinDate != null)
				return false;
		} else if (!joinDate.equals(other.joinDate))
			return false;
		if (operators == null) {
			if (other.operators != null)
				return false;
		} else if (!operators.equals(other.operators))
			return false;
		if (status != other.status)
			return false;
		return true;
	}
}
